/**
 * @file CRhoTable.hpp Deklarácia triedy CRhoTable.
 *
 * @author Martin Kosorinský.
 * @date 1.4.2009.
 */

#ifndef CRHOTABLE_HEADER
#define CRHOTABLE_HEADER

#include "miraclExtensions.hpp"

/**
 * @brief Tabuľka s kľúčom typu (epoint*) a dvojicami (big,big) ako hodnotou.
 * Trieda reprezentujúca tabuľku, v ktorej predstavujú kľúče body na eliptickej krivke.
 * V usporiadanom poradí sú uchovávané sú dvojice "bod na eliptickej krivke" a "dvojica čísiel typu big".
 * Na uchovávanie údajov sa využíva @c STL kontajner @c unordered_map, ktorá poskytuje efektívne operácie
 * vkladania a hlavne hľadania položiek na základe kľúča.
 * @warning Pre staršie kompilátory je štruktúra @c unordered_map nahradená štandardnou @c map.
 */
class CRhoTable {
private:
    /**
     * @brief Kontajner, v ktorom budú uložené položky tabuľky.
     * Využíva sa STL kontajner @c unordered_map, ktorý pracuje na báze hashovacej tabuľku.
     */
    TRhoEpointList table;
public:
    /**
     * @brief Iterátor pre prístup k prvkom tabuľky.
     */
    typedef TRhoEpointList::iterator iterator;
    /**
     * @brief Konštantný iterátor prvkov tabuľky.
     */
    typedef TRhoEpointList::const_iterator const_iterator;
    /**
     * @brief Základný konštruktor.
     * Konštruktor nealokuje žiadne prostriedky, len volá defaultné konštruktory členských premenných.
     */
    CRhoTable();
    /**
     * @brief Kopírovací konštruktor.
     * Vytvára novú inštanciu objektu CRhoTable ako <i>hard-copy</i> inej existujúcej inštancie CRhoTable.
     * @param[in] tab je referencia na inštanciu CRhoTable, ktorá slúži ako zdroj kopírovania.
     */
    CRhoTable(const CRhoTable &tab);
    /**
     * @brief Deštruktor.
     * Zabezpečuje korektnú dealokáciu prostriedkov. Deštruktor zabezpečí dealokáciu dynamickej pamäti, na
     * ktorú odkazujú smerníky uložené ako kľúče a ich hodnoty. Na dealokáciu kľúčov využíva procedúru
     * epoint_free() a na dealokáciu hodnôt procedúru mirkill().
     */
    ~CRhoTable();
    /**
     * @brief Funkcia vráti počet položiek uložených v tabuľke (počet rôznych kľúčov).
     * @return Funkcia vráti počet položiek uložených v tabuľke.
     */
    inline size_t size() const {
        return table.size();
    };
    /**
     * @brief Boolovská funkcia
     * @return návratová hodnota je TRUE ak tabuľka neobsahuje žiadne položky, ináč vráti FALSE.
     */
    inline bool empty() const {
        return (table.size() == 0);
    };
    /**
     * @brief Funkcia vracia maximálny počet položiek, ktoré je možné do tabuľky umiestniť.
     * Výstup vyplýva z obmedzení použitého generického kontajneru.
     * @return Maximálny počet položiek, ktoré je možné do tabuľky umiestniť.
     */
    inline size_t max_size() const {
        return table.max_size();
    };
    /**
     * @brief Vyprázdni obsah tabuľky.
     * Všetky položky tabuľky sú odstránené vrátane korektnej dealokácie pamäti.
     */
    void clear();
    /**
     * @brief Funkcia vráti iterátor ukazujúci na prvú položku tabuľky.
     * @return Iterátor ukazujúci na prvú položku tabuľky.
     */
    inline iterator begin() {
        return table.begin();
    };
    /**
     * @brief Funkcia vráti konštantný iterátor ukazujúci na prvú položku tabuľky.
     * @return Iterátor ukazujúci na prvú položku tabuľky.
     */
    inline const_iterator begin() const {
        return table.begin();
    };
    /**
     * @brief Funkcia vráti iterátor ukazujúci za poslednú položku tabuľky.
     * @return Iterátor ukazujúci za poslednú položku tabuľky.
     */
    inline iterator end() {
        return table.end();
    };
    /**
     * @brief Funkcia vráti konštantný iterátor ukazujúci za poslednú položku tabuľky.
     * @return Iterátor ukazujúci za poslednú položku tabuľky.
     */
    inline const_iterator end() const {
        return table.end();
    };
    /**
     * @brief Vyhľadáva v tabuľke položku s kľúčom <i>point</i> a vracia iterátor ukazujúci na túto položku.
     * V prípade, že sa položka s daným kľúčom v tabuľke nenachádza, vráti iterátor ukazujúci
     * za poslednú položku tabuľky.
     * @param[in] P je kľúč, ktorý sa snažíme nájsť v tabuľke.
     * @return Konštantný iterátor ukazujúci na hľadanú položku. V prípade neúspechu hľadania
     * ukazuje za poslednú položku tabuľky.
     */
    inline const_iterator find(const epoint * P) const {
        return table.find((epoint*)P);
    };
    /**
     * @brief Rozširuje tabuľku o novú položku.
     * Tabuľka neumožňuje pridať dve rôzne položky s rovnakým kľúčom, a preto v prípade, že už
     * obsahuje položku s vkladaným kľúčom, nebude tabuľka rozšírená. Ak položku neobsahuje, do
     * tabuľky je pridaná nová.
     * Všetky položky tabuľky sú udržiavané zoradené na základe komparátora. Procedúra vykonáva
     * pred uložením hard-copy kľúča aj hodnoty. To znamená, že je dynamicky alokovaná pamäť, do ktorej
     * sú skopírované vstupné dáta a do tabuľky sú pridané smerníky na túto pamäť.
     * @see add(const big x, const big y, const big a, const big b)
     * @param[in] P je bod, ktorý predstavuje kľúčovú hodnotu položky vkladanej do tabuľky.
     * @param[in] a je typu big, predstavuje prvú hodnotu priradenú vkladanému kľúču.
     * @param[in] b je typu big, predstavuje druhú hodnotu priradenú vkladanému kľúču.
     */
    void add(const epoint * P, const big a, const big b);
    /**
     * @copydoc add(const epoint * P, const big a, const big b)
     * @see add(const epoint * P, const big a, const big b)
     * @param[in] x je prvá afínna súradnica bodu, ktorý predstavuje kľúčovú hodnotu položky vkladanej do tabuľky.
     * @param[in] y je druhá afínna súradnica bodu, ktorý predstavuje kľúčovú hodnotu položky vkladanej do tabuľky.
     * @param[in] a je typu big, predstavuje prvú hodnotu priradenú vkladanému kľúču.
     * @param[in] b je typu big, predstavuje druhú hodnotu priradenú vkladanému kľúču.
     */
    void add(const big x, const big y, const big a, const big b);
    /**
     * @brief Operátor priradenia.
     * Vytvára hard-copy tabuľky na základe vstupného parametra.
     * @param[in] tab je existujúca inštancia tabuľky CRhoTable na základe ktorej vytvárame kópiu.
     * @return Referenciu na novovytvorenú inštanciu CRhoTable vytvorenú ako kópiu inej inštancie.
     */
    CRhoTable& operator=(const CRhoTable& tab);
    /**
     * @brief Procedúra binárne serializuje obsah tabuľky do súboru.
     * Procedúra zapíše obsah celej tabuľky do binárneho súboru, tak, aby bola možná ich obnova procedúrou
     * #load. Pred samotnými dátami je uložený počet položiek tabuľky (unsigned long). Následne sú sekvenčne
     * uložené položky tabuľky vo formáte:
     * - znamienko uložené čísla (1B).
     * - bajtová dĺžka uloženého čísla (1B).
     * - samotné bajty (dĺžka podľa predošlého bajtu).
     * Každá položka tabuľky obsahuje 4 takto serializované čísla typu @c big (x,y,a,b).
     * @warning Serializačné procedúry neošetrujú little-big endinaness ani dĺžku atomických dátových typov,
     * čo znamená, že dátové súbory nie sú prenositeľné medzi platformami.
     * @warning Procedúru je možné použiť len na uloženie čísiel, ktoré je možné zapísať do 256 bajtov.
     * @param[in] fileName Cesta k súboru, do ktorého chceme zapísať dáta.
     * @return Vráti TRUE v prípade úspešného uloženia dát do súboru, v opačnom prípade vráti FALSE.
     */
    bool save(std::string fileName);
    /**
     * @brief Procedúra načíta binárne serializovaný obsah tabuľky zo súboru.
     * Procedúra načíta do tabuľky dáta z binárneho súboru. Jeho formát je definovaný procedúrou #save.
     * Pred načítaním nie je zmazaný obsah tabuľky, nové položky sú pridávané do už existujúcej (ak tam také
     * už nie sú). Dáta v súboroch (hlavne počet uložených položiek) nemusia byť platformovo nezávisle, a preto treba s
     * procedúrami narábať obzvlášť opatrne. Pri vkladaní do tabuľky nedochádza ku žiadnej kontrole integrity dát. Avšak
     * v prípade pokusu o pridanie bodu, ktorý neleží na krivke, je program ukončený s chybou.
     * @param[in] fileName Cesta k súboru, z ktorého chceme načítať dáta.
     * @return Vráti TRUE v prípade úspešného načítania dát zo súboru, v opačnom prípade vráti FALSE.
     */
    bool load(std::string fileName);
};
#endif /* CRHOTABLE_HEADER */
